{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "775ca6a3-d589-4c12-948b-f3753a00329c",
   "metadata": {},
   "outputs": [],
   "source": [
    "# File: fishingknot.ipynb\n",
    "# Code: Claude Code and Codex\n",
    "# Review: Ryoichi Ando (ryoichi.ando@zozo.com)\n",
    "# License: Apache v2.0"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "bc4129bb-9186-468d-a0c5-9cf44414f120",
   "metadata": {},
   "outputs": [],
   "source": [
    "import os\n",
    "import tempfile\n",
    "\n",
    "import gdown\n",
    "from frontend import App\n",
    "\n",
    "# download the fishing knot mesh if not already present\n",
    "fishingknot_path = os.path.join(tempfile.gettempdir(), \"fishingknot.ply\")\n",
    "if not os.path.exists(fishingknot_path):\n",
    "    fishingknot_id = \"1alCDncsmGAFliL1YsPXzqr3pJJvs48P-\"\n",
    "    gdown.download(id=fishingknot_id, output=fishingknot_path)\n",
    "\n",
    "# create an app\n",
    "app = App.create(\"fishingknot\")\n",
    "\n",
    "# load the fishing knot ribbon mesh\n",
    "V, F = app.mesh.load_tri(fishingknot_path)\n",
    "app.asset.add.tri(\"ribbon\", V, F)\n",
    "\n",
    "# create a torus mesh\n",
    "V, F = app.mesh.torus(r=0.5, R=0.125)\n",
    "app.asset.add.tri(\"torus\", V, F)\n",
    "\n",
    "# create a scene\n",
    "scene = app.scene.create()\n",
    "\n",
    "# add ribbon with directional color and pin configuration\n",
    "ribbon = scene.add(\"ribbon\").jitter().direction_color(-1, 0, 0)\n",
    "ribbon.pin(ribbon.grab([-1, 0, 0], 0.4)).pull(1000.0).move_by([-10, 0, 0], 0, 18)\n",
    "ribbon.pin(ribbon.grab([0, -1, 0], 0.1))\n",
    "\n",
    "# set ribbon material properties\n",
    "(\n",
    "    ribbon.param.set(\"model\", \"arap\")\n",
    "    .set(\"bend\", 100.0)\n",
    "    .set(\"young-mod\", 1000)\n",
    "    .set(\"contact-gap\", 1e-3)\n",
    "    .set(\"strain-limit\", 0.05)\n",
    "    .set(\"friction\", 0.0)\n",
    ")\n",
    "\n",
    "# add torus as a fixed obstacle\n",
    "torus = scene.add(\"torus\").at(4.55, 1.2, 0.05)\n",
    "torus.pin()\n",
    "torus.param.set(\"friction\", 0.0)\n",
    "\n",
    "# compile the scene and report stats\n",
    "scene = scene.build().report()\n",
    "\n",
    "# preview the initial scene\n",
    "scene.preview()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "72e9a486-a231-4938-ab1f-09253e3009a8",
   "metadata": {},
   "outputs": [],
   "source": [
    "# create a new session with the compiled scene\n",
    "session = app.session.create(scene)\n",
    "\n",
    "# set session parameters - disable gravity for this simulation\n",
    "session.param.set(\"frames\", 830).set(\"gravity\", 0.0)\n",
    "\n",
    "# build this session\n",
    "session = session.build()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "3d3b8948-a0a3-4a26-96bd-fa68e4976467",
   "metadata": {},
   "outputs": [],
   "source": [
    "# start the simulation and live-preview the results\n",
    "session.start().preview()\n",
    "\n",
    "# also show simulation logs in realtime\n",
    "session.stream()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "7ffd0897-76d8-4751-8266-c8dbc40c5c96",
   "metadata": {},
   "outputs": [],
   "source": [
    "# create an animation from the simulation results\n",
    "session.animate()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "ff49a9f0-ac37-4325-b020-35f6322e37c3",
   "metadata": {},
   "outputs": [],
   "source": [
    "# export the animation to file\n",
    "session.export.animation()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "ae4b1170-6eba-4910-9d37-8c355841a832",
   "metadata": {},
   "outputs": [],
   "source": [
    "# this is for CI\n",
    "if app.ci:\n",
    "    assert session.finished()"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.12.3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
